package com.leonzx.base.service.system;

import com.leonzx.base.config.init.UserInit;
import com.leonzx.base.config.security.Digests;
import com.leonzx.base.constants.IMConstants;
import com.leonzx.base.dao.system.UserDAO;
import com.leonzx.base.entity.system.User;
import com.leonzx.base.service.BaseService;
import com.leonzx.base.service.RedisService;
import com.leonzx.base.utils.Constants;
import com.leonzx.base.utils.RedisConstants;
import com.leonzx.base.utils.SQLUtils;
import com.leonzx.base.utils.UUIDUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.DefaultSessionKey;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.io.Serializable;
import java.util.Date;
import java.util.Deque;
import java.util.List;
import java.util.Objects;

/**
 * @Author:梁亮
 * @Description:
 * @Date: 2018/6/4 17:40
 */
@Service
public class UserService extends BaseService {

    @Autowired
    private UserDAO userDAO;

    @Autowired
    private DefaultWebSessionManager sessionManager;

    @Autowired
    private RedisService redisService;

    @Autowired
    private RedisCacheManager cacheManager;

    public User getByUsername(String username) {
        User user = new User();
        user.setUsername(username);
        return userDAO.selectOne(user);
    }

    /**
     * 创建超级管理员
     *
     * @return
     */
    public int createAdmin() {
        User user = new User();
        //主键ID
        user.setId(UserInit.ADMIN);
        user.setUsername(UserInit.ADMIN);
        String password = Digests.md5(UserInit.ADMIN_PASSWORD, UserInit.ADMIN, Digests.HASH_INTERATIONS);
        user.setPassword(password);
        user.setName(UserInit.ADMIN_NAME);
        user.setState(Constants.STATE_VAILD);
        return userDAO.insert(user);
    }

    /**
     * 根据User包含的条件，查询所有符合条件的用户数据
     *
     * @param user
     * @return
     */
    public List<User> getAllByUser(User user) {

        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();

        if (StringUtils.isNotBlank(user.getUsername())) {
            criteria.andLike("username", SQLUtils.like(user.getUsername()));
        }

        if (StringUtils.isNotBlank(user.getName())) {
            criteria.andLike("name", SQLUtils.like(user.getName()));
        }

        if (user.getState() != null) {
            criteria.andEqualTo("state", user.getState());
        }
        return userDAO.selectByExample(example);
    }

    /**
     * 根据ID查询用户名称
     *
     * @param id
     * @return
     */
    public String getUserNameById(String id) {
        String userName = "";
        if (StringUtils.isNotBlank(id)) {
            User user = userDAO.selectByPrimaryKey(id);
            if (user != null) {
                userName = user.getName();
            }
        }
        return userName;
    }

    /**
     * 新增用户
     *
     * @param user
     */
    public void insert(User user) {
        user.setId(UUIDUtils.getUUID());
        user.setCreateTime(new Date());
        user.setState(Constants.STATE_VAILD);
        //IM默认为在线状态
        user.setImSign(IMConstants.IM_STATUS_ONLINE);

        String password = Digests.md5("111111", user.getUsername(), Digests.HASH_INTERATIONS);
        user.setPassword(password);
        userDAO.insert(user);
    }

    /**
     * 只改变用户状态，启用禁用
     *
     * @param user
     */
    public void changeState(User user) {
        userDAO.updateByPrimaryKeySelective(user);
    }

    /**
     * 重置密码
     *
     * @param user
     */
    public void resetPassword(User user) {
        String password = Digests.md5("111111", user.getUsername(), Digests.HASH_INTERATIONS);
        user.setPassword(password);
        userDAO.updateByPrimaryKeySelective(user);
    }

    /**
     * 根据User id查询user
     *
     * @param
     */
    public User getUserById(String id) {
        User user = new User();
        user.setId(id);
        return userDAO.selectOne(user);
    }

    /**
     * 根据id更新已有信息
     *
     * @param user
     */
    public void update(User user) {
        userDAO.updateByPrimaryKeySelective(user);
    }

    /**
     * @param usernames
     */
    public List<User> getUserByUsernames(List<String> usernames, String name, String username) {
        return userDAO.findUserByUsernames(usernames, name, username);
    }

    /**
     * @param username
     */
    public void outLine(String username) {
        Cache<String, Deque<Serializable>> cache = cacheManager.getCache(RedisConstants.SHIRO_REDIS_CACHE);
        Deque<Serializable> deque = cache.get(username);
        if (!Objects.isNull(deque)) {
            Serializable kickoutSessionId = deque.removeFirst();
            //获取被踢出的sessionId的session对象
            Session kickoutSession = sessionManager.getSession(new DefaultSessionKey(kickoutSessionId));
            if (kickoutSession != null) {
                //设置会话的kickout属性表示踢出了
                kickoutSession.setAttribute("kickout", true);
                kickoutSession.setAttribute("repeat", false);
            }
            //删除缓存
            redisService.remove("shiro:cache:" + RedisConstants.SHIRO_REDIS_CACHE + username);
        }
    }

    /**
     * @param id
     */
    public void outLineByUserId(String id) {
        User user = getUserById(id);
        if (user != null) {
            outLine(user.getUsername());
        }
    }

    public String findIdByUserName(String username) {
        return userDAO.findIdByUserName(username);
    }

    public List<User> findUserByRoleId(String id) {
        return userDAO.findUserByRoleId(id);
    }

    /**
     *
     * @param status
     * @param userId
     */
    @Transactional
    public void changeImStatusById(String status, String userId) {
        User user = new User();
        user.setImStatus(status);
        user.setId(userId);
        userDAO.updateByPrimaryKeySelective(user);
    }

    /**
     *
     * @param sign
     * @param userId
     */
    @Transactional
    public void changeImSignById(String sign, String userId) {
        User user = new User();
        user.setImSign(sign);
        user.setId(userId);
        userDAO.updateByPrimaryKeySelective(user);
    }
}
